home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dlink / module.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  16.6 KB  |  687 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  MODULE.C
  9.  *
  10.  */
  11.  
  12. #include "defs.h"
  13.  
  14. #define LINE    0x4C494E45
  15.  
  16. Prototype Module    *CreateModule(FileNode *);
  17. Prototype int    CreateSymbolTable(Module *);
  18. Prototype int    ScanLibForInclusion(Module *);
  19. Prototype void    CreateHunkListNodes(Module *, List *);
  20. Prototype void    FinalCombineHunkListNodes(List *);
  21. Prototype void    FixInternalSymbols(List *);
  22. Prototype void    PIOptCombineIntoCode(List *);
  23.  
  24. /*
  25.  *  Given a file node and a fully loaded file create a Module structure for
  26.  *  that node.    Set the Node->ln_Type to the file node's type.
  27.  *
  28.  *  This routine creates a *single* module .. that is, it stops if it reaches
  29.  *  a second hunk_unit.
  30.  */
  31.  
  32. Module *
  33. CreateModule(fn)
  34. FileNode *fn;
  35. {
  36.     Module *mod = zalloc(sizeof(Module));
  37.  
  38.     ++MemNumModules;
  39.     mod->Node.ln_Type = fn->Node.ln_Type;
  40.     mod->FNode = fn;
  41.  
  42.     /*
  43.      *    Do a validity scan and incidently count the number of hunks you
  44.      *    find.
  45.      */
  46.  
  47.     mod->ModBeg = (char *)fn->DPtr;
  48.     {
  49.     ulong *scan = fn->DPtr;
  50.     ulong *scanEnd = (ulong *)((char *)fn->Data + fn->Bytes);
  51.     long nl;
  52.  
  53.     /*
  54.      *  look for hunk_unit
  55.      */
  56.  
  57.     if ((uword)FromMsbOrder(*scan) != 0x3E7)
  58.         cerror(EFATAL_OBJECT_PARSE, fn->Node.ln_Name, (char *)fn->DPtr - (char *)fn->Data);
  59.  
  60.     nl = FromMsbOrder(scan[1] * 4);
  61.     mod->Node.ln_Name = zalloc(nl + 1);
  62.     movmem(scan + 2, mod->Node.ln_Name, nl);
  63.     mod->Node.ln_Name[nl] = 0;
  64.  
  65.     scan += FromMsbOrder(scan[1]) + 2;
  66.  
  67.     /*
  68.      *  scan hunks for the module.
  69.      */
  70.  
  71.     while (scan < scanEnd && (uword)FromMsbOrder(*scan) != 0x3E7) {
  72.         ++mod->NumHunks;        /*  # hunks in module        */
  73.  
  74.         if ((uword)FromMsbOrder(*scan) == 0x3E8) {
  75.         scan += FromMsbOrder(scan[1]) + 2;    /*  skip hunk_name        */
  76.         }
  77.  
  78.         while (FromMsbOrder(*scan) != 0x3F2) { /*  until we get a hunk_end */
  79.         ulong len;
  80.  
  81.         switch((uword)FromMsbOrder(*scan)) {
  82.         case 0x3E9:        /*  HUNK_CODE        */
  83.         case 0x3EA:        /*  HUNK_DATA        */
  84.             scan += FromMsbOrder(scan[1]) + 2;
  85.             break;
  86.         case 0x3EB:        /*  HUNK_BSS        */
  87.             scan += 2;
  88.             break;
  89.         case 0x3EC:        /*  HUNK_RELOC32    */
  90.         case 0x3ED:        /*  HUNK_RELOC16-PC */
  91.         case 0x3EE:        /*  HUNK_RELOC8     */
  92.         case 0x3F8:        /*  HUNK_RELOC16-D  (special) */
  93.             ++scan;
  94.             while (FromMsbOrder(*scan))
  95.             scan += FromMsbOrder(*scan) + 2;
  96.             ++scan;
  97.             break;
  98.         case 0x3EF:        /*  HUNK_EXT        */
  99.         case 0x3F0:        /*  HUNK_SYMBOL     */
  100.             ++scan;
  101.             while ((len = FromMsbOrder(*scan)) != 0) {
  102.             ubyte type = len >> 24;
  103.  
  104.             len &= 0x00FFFFFF;
  105.             scan += len + 1;
  106.  
  107.             switch(type) {
  108.             case 0:     /*  SYMB    */
  109.             case 1:     /*  DEF     */
  110.             case 2:     /*  ABS     */
  111.             case 3:     /*  RES     */
  112.                 ++scan;    /*  skip value    */
  113.                 break;
  114.             case 130:    /*  COMMON (def)*/
  115.                 /*fatal("COMMON symbol not supported, module %s", fn->Node.ln_Name);*/
  116.                 ++scan;    /*  skip common size */
  117.                 break;
  118.             case 135:    /*  REF32-pc    */
  119.             case 129:    /*  REF32    */
  120.             case 131:    /*  REF16-pc    */
  121.             case 132:    /*  REF8    */
  122.             case 134:    /*  REF16D    */
  123.                     /*  skip relocation info */
  124.                 scan += FromMsbOrder(scan[0]) + 1;
  125.                 break;
  126.             default:
  127.                 cerror(EFATAL_UNKNOWN_SYMBOL_TYPE, type, fn->Node.ln_Name);
  128.             }
  129.             }
  130.             ++scan;    /*  skip 0 terminator */
  131.             break;
  132.         case 0x3F1:        /*  HUNK_DEBUG        */
  133.             scan += FromMsbOrder(scan[1]) + 2;
  134.             break;
  135.         default:
  136.             cerror(EFATAL_UNKNOWN_HUNK_TYPE, *scan, fn->Node.ln_Name);
  137.         }
  138.         }
  139.         ++scan;    /*  skip hunk_end   */
  140.     }
  141.     if (scan > scanEnd)
  142.         cerror(EFATAL_OBJECT_SIZE_MISMATCH, fn->Node.ln_Name);
  143.     }
  144.  
  145.     /*
  146.      *    Allocate some stuff
  147.      */
  148.  
  149.     mod->Hunks = zalloc(sizeof(Hunk *) * mod->NumHunks);
  150.     MemNumHunks += mod->NumHunks;
  151.  
  152.     /*
  153.      *    Do a load scan
  154.      */
  155.  
  156.     {
  157.     ulong *scan = fn->DPtr;
  158.     ulong *scanEnd = (ulong *)((char *)fn->Data + fn->Bytes);
  159.     short hunkNo = 0;
  160.  
  161.     /*
  162.      *  look for hunk_unit
  163.      */
  164.  
  165.     if ((uword)FromMsbOrder(*scan) != 0x3E7)
  166.         cerror(EFATAL_146);
  167.     scan += FromMsbOrder(scan[1]) + 2;
  168.  
  169.     /*
  170.      *  scan hunks for the module.
  171.      */
  172.  
  173.     while (scan < scanEnd && (uword)FromMsbOrder(*scan) != 0x3E7) {
  174.         Hunk *hunk = zalloc(sizeof(Hunk));
  175.         ++MemNumHunks;
  176.  
  177.         if (hunkNo >= mod->NumHunks)
  178.         cerror(EFATAL_TOO_MANY_HUNKS);
  179.  
  180.         mod->Hunks[hunkNo] = hunk;
  181.         hunk->HunkNo = hunkNo;
  182.         hunk->Module = mod;
  183.         NewList(&hunk->SymList);    /*  only used if SymOpt     */
  184.         ++hunkNo;
  185.  
  186.         /*
  187.          *    hunk name.  If section name starts with 'far' or in
  188.          *    dummy flag to upper bits of hunkid to force the hunk
  189.          *    to remain outside normal data+bss small model combine.
  190.          */
  191.  
  192.         if ((uword)FromMsbOrder(*scan) == 0x3E8) {
  193.         long nl = FromMsbOrder(scan[1]) * 4;
  194.         hunk->Node.ln_Name = zalloc(nl + 1);
  195.         movmem(scan + 2, hunk->Node.ln_Name, nl);
  196.         hunk->Node.ln_Name[nl] = 0;
  197.         if (strnicmp(hunk->Node.ln_Name, "far", 3) == 0)
  198.             hunk->HunkId |= HUNKIDF_FLAG;
  199.         scan += FromMsbOrder(scan[1]) + 2;        /*    skip hunk_name        */
  200.         } else {
  201.         hunk->Node.ln_Name = "";
  202.         }
  203.  
  204.             /*  until we get a hunk_end */
  205.  
  206.         while ((uword)FromMsbOrder(*scan) != 0x3F2) {  
  207.         ulong len;
  208.  
  209.         switch((uword)FromMsbOrder(*scan)) {
  210.         case 0x3E9:        /*  HUNK_CODE        */
  211.             hunk->HunkId |= FromMsbOrder(*scan);
  212.             hunk->Node.ln_Type = NT_CODE;
  213.             hunk->Data = scan + 2;
  214.             hunk->Bytes= FromMsbOrder(scan[1]) << 2;
  215.             scan += FromMsbOrder(scan[1]) + 2;
  216.             break;
  217.         case 0x3EA:        /*  HUNK_DATA        */
  218.             hunk->HunkId |= FromMsbOrder(*scan);
  219.             hunk->Node.ln_Type = NT_DATA;
  220.             hunk->Data = scan + 2;
  221.             hunk->Bytes= FromMsbOrder(scan[1]) << 2;
  222.             scan += FromMsbOrder(scan[1]) + 2;
  223.             break;
  224.         case 0x3EB:        /*  HUNK_BSS        */
  225.             hunk->HunkId |= FromMsbOrder(*scan);
  226.             hunk->Node.ln_Type = NT_BSS;
  227.             hunk->Data = NULL;
  228.             hunk->Bytes = FromMsbOrder(scan[1]) << 2;
  229.             scan += 2;
  230.             break;
  231.         case 0x3F8:        /*  HUNK_RELOC16-D  */
  232.             hunk->Reloc16D = scan + 1;
  233.             /* fall through */
  234.         case 0x3EC:        /*  HUNK_RELOC32    */
  235.             if (FromMsbOrder(*scan) == 0x3EC)
  236.             hunk->Reloc32 = scan + 1;
  237.             /* fall through */
  238.         case 0x3ED:        /*  HUNK_RELOC16    */
  239.             if (FromMsbOrder(*scan) == 0x3ED)
  240.             hunk->Reloc16 = scan + 1;
  241.             /* fall through */
  242.         case 0x3EE:        /*  HUNK_RELOC8     */
  243.             if (FromMsbOrder(*scan) == 0x3EE)
  244.             hunk->Reloc8 = scan + 1;
  245.             ++scan;
  246.             while (FromMsbOrder(*scan))
  247.             scan += FromMsbOrder(*scan) + 2;
  248.             ++scan;
  249.             break;
  250.         case 0x3EF:        /*  HUNK_EXT        */
  251.             hunk->Ext = scan + 1;
  252.             /* fall through */
  253.         case 0x3F0:        /*  HUNK_SYMBOL     */
  254.             if (FromMsbOrder(*scan) == 0x3F0)
  255.             hunk->Sym = scan + 1;
  256.             ++scan;
  257.             while ((len = FromMsbOrder(*scan)) != 0) {
  258.             ubyte type = len >> 24;
  259.  
  260.             len &= 0x00FFFFFF;
  261.             scan += len + 1;
  262.  
  263.             switch(type) {
  264.             case 0:     /*  SYMB    */
  265.             case 1:     /*  DEF     */
  266.             case 2:     /*  ABS     */
  267.             case 3:     /*  RES     */
  268.                 if (type != 2)
  269.                 ++hunk->ExtDefs;
  270.                 ++scan;    /*  skip value    */
  271.                 break;
  272.             case 130:    /*  COMMON  */
  273.                 /*fatal("COMMON symbol not supported");*/
  274.                 /*++hunk->ExtDefs;*/
  275.                 ++scan;    /*  skip common size */
  276.                 break;
  277.             case 135:    /*  REF32-pc    */
  278.             case 129:    /*  REF32    */
  279.             case 131:    /*  REF16-pc    */
  280.             case 132:    /*  REF8    */
  281.             case 134:    /*  REF16D    */
  282.                     /*  skip relocation info */
  283.                 scan += FromMsbOrder(scan[0]) + 1;
  284.                 break;
  285.             }
  286.             }
  287.             ++scan;    /*  skip 0 terminator */
  288.             break;
  289.         case 0x3F1:        /*  HUNK_DEBUG        */
  290.             if (((DBInfo *)scan)->di_LINE == LINE)
  291.             hunk->DbInfo = (DBInfo *)scan;
  292.             scan += FromMsbOrder(scan[1]) + 2;
  293.             break;
  294.         }
  295.         }
  296.         ++scan;    /*  skip hunk_end   */
  297.         hunk->TotalBytes = hunk->Bytes;
  298.         if (hunk->Node.ln_Type == 0)
  299.         cerror(EERROR_NO_CODE_DATA_BSS, hunk->Node.ln_Name, hunk->Module->Node.ln_Name);
  300.     }
  301.     fn->DPtr = scan;
  302.     if (hunkNo < mod->NumHunks)
  303.         cerror(EFATAL_TOO_FEW_HUNKS);
  304.     if (hunkNo > mod->NumHunks)
  305.         cerror(EFATAL_TOO_MANY_HUNKS);
  306.     mod->ModEnd = (char *)fn->DPtr;
  307.     }
  308.  
  309.     return(mod);
  310. }
  311.  
  312. /*
  313.  *  run SCAN_RELOC_SYMIN on all external symbol tables for all hunks in
  314.  *  this module.
  315.  *
  316.  *  returns number of newly undefined symbols that have been created
  317.  *  (referencing symbols that are already undefined ... previously
  318.  *  referenced and still not defined, do not count in the count)
  319.  */
  320.  
  321. int
  322. CreateSymbolTable(mod)
  323. Module *mod;
  324. {
  325.     short i;
  326.     long r = 0;
  327.  
  328.     for (i = 0; i < mod->NumHunks; ++i)
  329.     r += ScanHunkExt(mod->Hunks[i], SCAN_RELOC_SYMIN);
  330.     return(r);
  331. }
  332.  
  333. /*
  334.  *  returns true if this module, part of a library, contains definitions
  335.  *  used by previously loaded modules
  336.  */
  337.  
  338. int
  339. ScanLibForInclusion(mod)
  340. Module *mod;
  341. {
  342.     short i;
  343.  
  344.     for (i = 0; i < mod->NumHunks; ++i) {
  345.     if (ScanHunkExt(mod->Hunks[i], SCAN_RELOC_SYMCK))
  346.         return(1);
  347.     }
  348.     return(0);
  349. }
  350.  
  351. /*
  352.  *  This is the great coagulator... hlist begins empty.  We allocate a
  353.  *  master HunkListNode for each 'hunk' in the final output, adding hunks
  354.  *  that appear in the module to the appropriate HunkListNode.
  355.  *
  356.  *  We can never combine hunks with different HunkId's (including the
  357.  *  upper bits)
  358.  *
  359.  *  We must also keep sections in order.
  360.  *
  361.  *  Note that only hunks with the same HunkListNode may run PC relative
  362.  *  references to each other.
  363.  */
  364.  
  365. void
  366. CreateHunkListNodes(mod, hlist)
  367. Module *mod;
  368. List *hlist;
  369. {
  370.     short i;
  371.  
  372.     for (i = 0; i < mod->NumHunks; ++i) {
  373.     Hunk *hunk;
  374.     Hunk *h;
  375.     HunkListNode *hn;
  376.  
  377.     hunk = mod->Hunks[i];
  378.  
  379.     /*
  380.      *  Search for the hunk type & name amoung HunkListNode type and names.
  381.      *  If not found, append a new HunkListNode.   Give HunkListNode's
  382.      *  priorities:
  383.      *            64    NT_CODE
  384.      *            32    NT_DATA
  385.      *            16    NT_BSS
  386.      */
  387.  
  388.     for (hn = GetHead(hlist); hn; hn = GetSucc(&hn->Node)) {
  389.         if (hn->HunkId != hunk->HunkId)
  390.         continue;
  391. #ifdef NOTDEF
  392.         /*
  393.          *  if data or bss
  394.          */
  395.         if ((uword)hn->HunkId == (uword)hunk->HunkId) {
  396.             if (hn->Node.ln_Type == NT_DATA || hn->Node.ln_Type == NT_BSS) {
  397.             if (ResOpt) {
  398.                 cerror(EWARN_CANNOT_COAG_DATABSS);
  399.                 ResOpt = 0;
  400.             }
  401.             }
  402.         }
  403.         continue;
  404.         }
  405. #endif
  406.         /*
  407.          *    Ignore section names for -r or -pi/-pr
  408.          */
  409.  
  410.         if (PIOpt || ResOpt)
  411.         break;
  412.  
  413.         /*
  414.          *    Collect if the same section name
  415.          */
  416.  
  417.         if (strcmp(hn->Node.ln_Name, hunk->Node.ln_Name) == 0)
  418.         break;
  419.  
  420.         /*
  421.          *    collection of differently named hunks only works if -frag
  422.          *    is not specified AND the hunks are normal hunks (no upper
  423.          *    bits set)
  424.          *
  425.          *    hunk names that begin with 'far' have a dummy upper bit set
  426.          */
  427.  
  428.         if (FragOpt == 0 && (hunk->HunkId & 0xFFFF0000) == 0)
  429.         break;
  430.     }
  431.     if (hn == NULL) {
  432.         hn = zalloc(sizeof(HunkListNode));
  433.         hn->Node.ln_Type = hunk->Node.ln_Type;
  434.         hn->Node.ln_Name = hunk->Node.ln_Name;
  435.         hn->HunkId = hunk->HunkId;
  436.  
  437.         switch(hn->Node.ln_Type) {
  438.         case NT_CODE:
  439.         hn->Node.ln_Pri = 64;
  440.         break;
  441.         case NT_DATA:
  442.         hn->Node.ln_Pri = 32;
  443.         break;
  444.         case NT_BSS:
  445.         hn->Node.ln_Pri = 16;
  446.         break;
  447.         default:
  448.         hn->Node.ln_Pri = 8;
  449.         break;
  450.         }
  451.         Enqueue(hlist, &hn->Node);
  452.         NewList(&hn->HunkList);
  453.     }
  454.     /*
  455.      *  Put the hunk after other hunks of the same name.
  456.      */
  457.  
  458.     for (h = GetHead(&hn->HunkList); h; h = GetSucc(&h->Node)) {
  459.         if (strcmp(h->Node.ln_Name, hunk->Node.ln_Name) == 0)
  460.         break;
  461.     }
  462.     while (h && strcmp(h->Node.ln_Name, hunk->Node.ln_Name) == 0)
  463.         h = GetSucc(&h->Node);
  464.  
  465.     if (h)            /*  insert after last name that compared */
  466.         h = GetPred(&h->Node);    /*  or head of list */
  467.     else            /*  couldn't find anything, append to end */
  468.         h = GetTail(&hn->HunkList);
  469.  
  470.     Insert(&hn->HunkList, &hunk->Node, &h->Node);
  471.     hunk->HL = hn;
  472.     hunk->HX = hn;
  473.     hn->FinalExtDefs += hunk->ExtDefs;
  474.     }
  475. }
  476.  
  477. /*
  478.  *  If we are not running fragmented this routine places all BSS sections
  479.  *  after DATA sections.  Currently this is only done for unqualified
  480.  *  hunks (e.g. that can go into any type of memory).
  481.  *
  482.  *  e.g. this routine combines the DATA and BSS sections
  483.  *
  484.  *  note that due to enqueue priority DATA sections will come before BSS
  485.  *  sections.
  486.  *
  487.  *  note that any section name beginning with 'far' has a HUNKIDF_FLAG
  488.  *  set in its HunkId so it will not be improperly combined.
  489.  */
  490.  
  491. void
  492. FinalCombineHunkListNodes(hlist)
  493. List *hlist;
  494. {
  495.     HunkListNode *hn;
  496.     HunkListNode *hn_next;
  497.     HunkListNode *hndata = NULL;
  498.     Hunk *h;
  499.  
  500.     if (FragOpt)
  501.     return;
  502.     for (hn = GetHead(hlist); hn; hn = hn_next) {
  503.     hn_next = GetSucc(&hn->Node);
  504.     if (hn->Node.ln_Type == NT_DATA && (hn->HunkId & 0xFFFF0000) == 0) {
  505.         hndata = hn;
  506.         for (h = (Hunk *)GetHead(&hn->HunkList); h; h = (Hunk *)GetSucc(&h->Node)) {
  507.         h->Flags |= HF_SMALLDATA;
  508.         }
  509.     }
  510.  
  511.     if (hn->Node.ln_Type == NT_BSS && (hn->HunkId & 0xFFFF0000) == 0) {
  512.         if (hndata) {
  513.         Remove(&hn->Node);
  514.         while ((h = (Hunk *)RemHead(&hn->HunkList)) != NULL) {
  515.             AddTail(&hndata->HunkList, &h->Node);
  516.             h->HL = hndata;
  517.             h->HX = hndata;
  518.             h->Flags |= HF_DATABSS | HF_SMALLDATA;
  519.             hndata->FinalExtDefs += h->ExtDefs;
  520.         }
  521.         } else {
  522.         for (h = (Hunk *)GetHead(&hn->HunkList); h; h = GetSucc(&h->Node))
  523.             h->Flags |= HF_DATABSS;
  524.         hn->Node.ln_Type = NT_DATA;
  525.         hn->HunkId = 0x3EA;
  526.         hndata = hn;
  527.         }
  528.     }
  529.     }
  530. }
  531.  
  532.  
  533. /*
  534.  *  This routine fixes the symbol table for BSS sections combined with DATA
  535.  *  sections.  Note that if we are Frag'd there are no combined BSS sections.
  536.  *
  537.  *  Only unqualified sections are considered.  e.g. a CHIP ram section is not
  538.  *  considered.  qualified sections are assumed to be referenced with far
  539.  *  declarations.
  540.  *
  541.  *  It is still possible to have some far data & bss hunks.  The combine
  542.  *  only applies to the first two.
  543.  */
  544.  
  545. void
  546. FixInternalSymbols(list)
  547. List *list;
  548. {
  549.     HunkListNode *data = NULL;
  550.     HunkListNode *bss  = NULL;
  551.     HunkListNode *code = NULL;
  552.     Hunk *hunk;
  553.  
  554.     if (FragOpt)
  555.     return;
  556.  
  557.     {
  558.     HunkListNode *hn;
  559.     for (hn = GetHead(list); hn; hn = GetSucc(&hn->Node)) {
  560.         if ((hn->HunkId & 0xFFFF0000) == 0) {
  561.         if (hn->Node.ln_Type == NT_CODE)
  562.             code = hn;
  563.         if (hn->Node.ln_Type == NT_DATA) {
  564.             if (data == NULL)
  565.             data = hn;
  566.             else
  567.             cerror(EFATAL_556);
  568.         }
  569.         if (hn->Node.ln_Type == NT_BSS) {
  570.             if (bss == NULL)
  571.             bss = hn;
  572.             else
  573.             cerror(EFATAL_562);
  574.         }
  575.         }
  576.     }
  577.     }
  578.  
  579.     if (data == NULL)    /*  no data anyway  */
  580.     return;
  581.     if (bss && !FragOpt)
  582.     cerror(EFATAL_571);
  583.  
  584.     hunk = GetHead(&data->HunkList);
  585.     if (hunk == NULL)
  586.     cerror(EFATAL_DATA_HUNK_EMPTY);
  587.  
  588.     BssLenSym->Hunk = hunk;
  589.     BssLenSym->Value= data->AddSize >> 2;
  590.  
  591.     if (SymOpt) {
  592.     AddTail(&hunk->SymList, (Node *)&BssLenSym->Node);
  593.     BssLenSym->Flags |= SYMF_SYMLIST;
  594.     }
  595.  
  596.     if (AbsWordOpt || PIOpt) {
  597.     /*
  598.      *  AbsWordOpt: __ABSOLUTE_BAS address already set to absolute value
  599.      */
  600.     if (code && (hunk = GetTail(&code->HunkList))) {
  601.         DataBasSym->Type = 1;
  602.         DataBasSym->Hunk = hunk;
  603.         DataBasSym->Value= /* hunk->Offset + */ hunk->TotalBytes;
  604.  
  605.         /*
  606.          *    position independant option, __ABSOLUTE_BAS and __DATA_BAS
  607.          *    point to the same thing and reside in code hunk so can be
  608.          *    accessed PC-relative
  609.          */
  610.  
  611.         if (PIOpt) {
  612.         AbsoluteBasSym->Type = 1;
  613.         AbsoluteBasSym->Hunk = hunk;
  614.         AbsoluteBasSym->Value= /* hunk->Offset + */ hunk->TotalBytes;
  615.         }
  616.     }
  617.     } else {
  618.     /*
  619.      *  must set __ABSOLUTE_BAS address to location of real data, but
  620.      *  only if the symbol exists (e.g. ResOpt == 0)
  621.      */
  622.     if (AbsoluteBasSym) {
  623.         AbsoluteBasSym->Type = 1;
  624.         AbsoluteBasSym->Hunk = hunk;
  625.     }
  626.  
  627.     DataBasSym->Type = 1;
  628.     DataBasSym->Hunk = hunk;
  629.     }
  630.     DataLenSym->Value = data->FinalSize >> 2;
  631.     if (SymOpt) {
  632.     AddTail(&hunk->SymList, (Node *)&DataBasSym->Node);
  633.     AddTail(&hunk->SymList, (Node *)&DataLenSym->Node);
  634.     DataBasSym->Flags |= SYMF_SYMLIST;
  635.     DataLenSym->Flags |= SYMF_SYMLIST;
  636.  
  637.     if (AbsoluteBasSym) {
  638.         AddTail(&hunk->SymList, (Node *)&AbsoluteBasSym->Node);
  639.         AbsoluteBasSym->Flags |= SYMF_SYMLIST;
  640.     }
  641.     }
  642.  
  643.     if (ResOpt)
  644.     IsResSym->Value = 1;
  645. }
  646.  
  647. /*
  648.  *  Position Independant option combine, Just before final output combine
  649.  *  all hunks into a single CODE hunk.    However, offsets for DATA & BSS
  650.  *  hunks are NOT modified because DATA & BSS is still referenced A4-REL.
  651.  *
  652.  *  There can be no 32 bit relocations
  653.  */
  654.  
  655. void
  656. PIOptCombineIntoCode(list)
  657. List *list;
  658. {
  659.     HunkListNode *hn;
  660.     HunkListNode *ht;
  661.     Hunk *hunk;
  662.  
  663.     hn = RemHead(list);
  664.     if (hn == NULL)
  665.     return;
  666.     if (hn->Node.ln_Type != NT_CODE) {
  667.     cerror(EERROR_PI_EXPECTED_CODE);
  668.     return;
  669.     }
  670.     while ((ht = RemHead(list)) != NULL) {
  671.     if (ht->Node.ln_Type == NT_CODE) {
  672.         cerror(EERROR_PI_EXPECTED_ONE_CODE);
  673.         return;
  674.     }
  675.     while ((hunk = RemHead(&ht->HunkList)) != NULL) {
  676.         if (hunk->Flags & HF_DATABSS)
  677.         hn->AddSize += (hunk->TotalBytes + 3) & ~3;
  678.         else
  679.         hn->FinalSize += (hunk->TotalBytes + 3) & ~3;
  680.         AddTail(&hn->HunkList, &hunk->Node);
  681.     }
  682.     }
  683.     NumExtHunks = 1;
  684.     AddHead(list, &hn->Node);
  685. }
  686.  
  687.